#include "Util.h"

#include <boost/assign.hpp>

namespace util {
void dbg(wstring ws) {
#ifdef _DEBUG
	::MessageBox(0, ws.c_str(), 0, 0);
#endif
}
void dbg(string s) {
#ifdef _DEBUG
	::MessageBoxA(0, s.c_str(), 0, 0);
#endif
}

wstring TrimSlash(wstring path) {
	while (path.length() > 0 && (path[0] == L'\\' || path[0] == L'/')) {
		path = path.substr(1);
	}
	while (path.length() > 0 && (path[path.length() - 1] == L'\\' || path[path.length() - 1] == L'/')) {
		path = path.substr(0, path.length() - 1);
	}
	return path;
}
wstring JoinPath(wstring path, wstring path1, wstring path2, wstring path3, wstring path4, wstring path5, wstring path6, wstring path7, wstring path8, wstring path9) {
	vector<wstring> vec;
	vec.push_back(path1);
	vec.push_back(path2);
	vec.push_back(path3);
	vec.push_back(path4);
	vec.push_back(path5);
	vec.push_back(path6);
	vec.push_back(path7);
	vec.push_back(path8);
	vec.push_back(path9);
	path = TrimSlash(path);
	for (vector<wstring>::size_type i = 0; i < vec.size(); ++i) {
		wstring s = TrimSlash(vec[i]);
		if (s.empty()) {
			break;
		} else {
			path += L"\\";
			path += s;
		}
	}
	return path;
}
wstring GetExeFile() {
	static wstring exepath;
	if (exepath.empty()) {
		wchar_t buf[MAX_PATH + 1] = { 0 };
		DWORD dw = ::GetModuleFileNameW(0, buf, MAX_PATH);
		buf[dw] = 0;
		exepath = buf;
	}
	return exepath;
}
wstring GetAppPath() {
	static wstring apppath;
	if (apppath.empty()) {
		wstring filepath = GetExeFile();
		wstring::size_type n = filepath.find_last_of(L'\\');
		apppath = filepath.substr(0, n);
	}
	return apppath;
}

void ProcessCurrentMesssage() {
	MSG msg = { 0 };
	while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
}

void OutStr(wstring ws) {
	ws += L"\n";
	OutputDebugStringW(ws.c_str());
}
void OutStr(string s) {
	s += "\n";
	OutputDebugStringA(s.c_str());
}
wstring ToWString(string s, DWORD cp) {
	DWORD dwMinSize = MultiByteToWideChar(cp, 0, s.c_str(), -1, NULL, 0);
	wchar_t* ws = new wchar_t[dwMinSize + 1];
	int n = MultiByteToWideChar(cp, 0, s.c_str(), -1, ws, dwMinSize);
	ws[n] = 0;
	wstring wstr(ws);
	delete[] ws;
	return wstr;
}
string ToString(wstring ws, DWORD cp) {
	DWORD dwMinSize = WideCharToMultiByte(cp, NULL, ws.c_str(), -1, NULL, 0, NULL, FALSE);
	char* buf = new char[dwMinSize + 1];
	int n = WideCharToMultiByte(cp, NULL, ws.c_str(), -1, buf, dwMinSize, NULL, FALSE);
	buf[n] = 0;
	string s(buf);
	delete[] buf;
	return s;
}

vector<string> OpenFileDialog(HWND parent, bool multi) {
	OPENFILENAMEA ofn = { 0 };
	char szFile[1024] = { 0 }; //NO MAX_PATH, multi select!
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = parent;
	ofn.lpstrFile = szFile;
	ofn.nMaxFile = 1024;
	ofn.lpstrFilter = "All(*.*)\0*.*\0Text(*.txt)\0*.txt\0\0";
	ofn.nFilterIndex = 1;
	ofn.lpstrFileTitle = NULL;
	ofn.nMaxFileTitle = 0;
	ofn.lpstrInitialDir = NULL;
	ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
	if (multi) {
		ofn.Flags |= OFN_ALLOWMULTISELECT;
	}

	vector<string> vec;
	if (GetOpenFileNameA(&ofn)) {
		string path = szFile;
		if (!multi) {
			vec.push_back(path);
			return vec;
		}
		char* p = szFile + path.length() + 1;
		if (!*p) {
			vec.push_back(path); //only select one file
			return vec;
		}

		path.append(1, '\\');
		while (*p) {
			string file = p;
			vec.push_back(path + file);
			p += file.length() + 1;
		}
		//return vec;
	}
	return vec;
}
string SaveFileDialog(HWND parent) {
	OPENFILENAME ofn = { 0 };
	char szFile[MAX_PATH] = { 0 };
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = parent;
	ofn.lpstrFile = szFile;
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrFilter = "All(*.*)\0*.*\0Text(*.txt)\0*.txt\0\0";
	ofn.nFilterIndex = 1;
	ofn.lpstrFileTitle = NULL;
	ofn.nMaxFileTitle = 0;
	ofn.lpstrInitialDir = NULL;
	ofn.Flags = OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_EXPLORER | OFN_HIDEREADONLY;
	if (GetSaveFileName(&ofn)) {
		return string(szFile);
	}
	return "";
}

int FontSizeToHeight(HDC dc, int size) {
	return -MulDiv(size, GetDeviceCaps(dc, LOGPIXELSY), 72);
}
int GenerateID() {
	static int id = 0;
	return id++;
}
void ShowLastError() {
	LPTSTR buf;
	DWORD err = GetLastError();
	::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, err, 0, (LPTSTR) &buf, 0, 0);
	dbg(buf);
	LocalFree(buf);
}

}
;

boost::any WithProperties::GetProperty(wstring propertyName, boost::any defaultValue) {
	PropertiesType::iterator it = properties_.find(propertyName);
	if (it != properties_.end()) {
		return it->second;
	}
	return defaultValue;
}
void WithProperties::SetProperty(wstring propertyName, boost::any value) {
	properties_[propertyName] = value;
}
